package routers

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"time"

	//log "github.com/sirupsen/logrus"
	"shqsoft.cn/pasnj/base"
	"shqsoft.cn/pasnj/entity"
	"shqsoft.cn/pasnj/popedom"
	"shqsoft.cn/pasnj/reports"

	"golang.org/x/text/language"
	"golang.org/x/text/message"

	jwt "github.com/dgrijalva/jwt-go"
	"github.com/labstack/echo"
)

// ReportInfoRouter ReportInfo路由
func ReportInfoRouter(c echo.Context) error {
	confName := c.Param("ConfigName")
	if confName == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "path参数ConfigName不能为空！")
	}
	rep, err := reports.NewReport(confName)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	repConf := rep.GetConfig()
	params := repConf.Params
	params2, paramMap, err := initReportParams(params)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	if err = rep.SetParams(paramMap); err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	count, err := rep.Create(nil, nil)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	cols := repConf.Columns
	colsBytes, err := json.Marshal(cols)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	params2Bytes, err := json.Marshal(params2)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	respStr := fmt.Sprintf(`{"columns":%s,"params":%s,"keyColumn":"%s","userIDColumn":"%s","totle":%d}`, string(colsBytes), string(params2Bytes), repConf.KeyColumn, repConf.UserIDColumn, count)
	return c.String(http.StatusOK, respStr)
}

// ACBL 余额
type ACBL struct {
	DTID string `json:"dtid"`
	ACBL string `json:"acbl"`
	INRT string `json:"inrt"`
}

// ReportACBLRouter ReportACBL路由
func ReportACBLRouter(c echo.Context) error {
	reportName := c.FormValue("reportName")
	rep, err := reports.NewReport(reportName)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	sdateStr := c.FormValue("sdate")
	if sdateStr == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "Form参数sdate不能为空！")
	}
	sdate, err := time.Parse("2006-01-02", sdateStr)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("参数sdate:%s不是有效的日期！", sdateStr))
	}
	edateStr := c.FormValue("edate")
	if edateStr == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "Form参数edate不能为空！")
	}
	edate, err := time.Parse("2006-01-02", edateStr)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("参数sdate:%s不是有效的日期！", edateStr))
	}
	acidStr := c.FormValue("acid")
	if acidStr == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "Form参数acid不能为空！")
	}
	acid, err := strconv.Atoi(acidStr)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("参数acid:%s不是有效的整数！", acidStr))
	}
	sql := rep.GetConfig().DataSQL["acbl"]
	if sql == "" {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("报表%s的DataSQL配置错误，没有发现acbl！", reportName))
	}
	rows, err := base.DB.Raw(sql, sdate.Format("20060102"), edate.Format("20060102"), acid).Rows()
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("执行报表%s的acblSQL出错，%s！", reportName, err.Error()))
	}
	defer rows.Close()
	print := message.NewPrinter(language.English)
	acblList := make([]ACBL, 0, 20)
	var acbl2 float64
	for rows.Next() {
		var dtid int
		var acbl float64
		rows.Scan(&dtid, &acbl)
		if acbl == acbl2 {
			continue
		}
		dtidBytes := []byte(strconv.Itoa(dtid))
		dtidStr := string(dtidBytes[:4]) + "-" + string(dtidBytes[4:6]) + "-" + string(dtidBytes[6:])
		obj := ACBL{
			DTID: dtidStr,
			ACBL: print.Sprintf("%.2f", acbl),
		}
		acblList = append(acblList, obj)
		acbl2 = acbl
	}
	return c.JSON(http.StatusOK, acblList)
}

// DIVI 认定关系
type DIVI struct {
	ID   int        `json:"id"`
	EMNO string     `json:"emno"`
	EMNM string     `json:"emnm"`
	DPNM string     `json:"dpnm"`
	DSTY string     `json:"dsty"`
	DSDT time.Time  `json:"dsdt"`
	WODT *time.Time `json:"wodt"`
	DSVL float64    `json:"dsvl"`
}

// ReportDIVIRouter ReportDIVI路由
func ReportDIVIRouter(c echo.Context) error {
	reportName := c.FormValue("reportName")
	rep, err := reports.NewReport(reportName)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	acidStr := c.FormValue("acid")
	if acidStr == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "Form参数acid不能为空！")
	}
	acid, err := strconv.Atoi(acidStr)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("参数acid:%s不是有效的整数！", acidStr))
	}
	sql := rep.GetConfig().DataSQL["divi"]
	if sql == "" {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("报表%s的DataSQL配置错误，没有发现divi！", reportName))
	}
	rows, err := base.DB.Raw(sql, acid).Rows()
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, fmt.Errorf("执行报表%s的diviSQL出错，%s！", reportName, err.Error()))
	}
	defer rows.Close()
	divdList := make([]DIVI, 0, 5)
	for rows.Next() {
		var id int
		var emno string
		var emnm string
		var dpnm string
		var dsty string
		var dsdt time.Time
		var wodt *time.Time
		var dsvl float64
		rows.Scan(&id, &emno, &emnm, &dpnm, &dsty, &dsdt, &wodt, &dsvl)
		divdList = append(divdList, DIVI{
			ID:   id,
			EMNO: emno,
			EMNM: emnm,
			DPNM: dpnm,
			DSTY: dsty,
			DSDT: dsdt,
			WODT: wodt,
			DSVL: dsvl,
		})
	}
	return c.JSON(http.StatusOK, divdList)
}

func initReportParams(params []reports.Parameter) ([]reports.Parameter, map[string]string, error) {
	count := len(params)
	params2 := make([]reports.Parameter, count, count)
	paramMap := make(map[string]string)
	for i, p := range params {
		if initV, err := getInitValue(p.InitVal); err == nil {
			params2[i] = reports.Parameter{
				Name:     p.Name,
				Caption:  p.Caption,
				DataType: p.DataType,
				InitVal:  initV,
			}
			paramMap[p.Name] = initV
		} else {
			return nil, nil, err
		}
	}
	return params2, paramMap, nil
}
func getInitValue(initValue string) (string, error) {
	var pasInfo entity.PASInfo
	err := base.DB.First(&pasInfo).Error
	if err != nil {
		return "", err
	}
	if strings.HasPrefix(initValue, "#") {
		var retVal string

		// if Sjy == "EDW" {
		// 	switch initValue {
		// 	case "#SYSDATE":
		// 		retVal = pasInfo.EdwCurrDate.Format("20060102")
		// 	case "#MONTHFIRSTDAY":
		// 		retVal = pasInfo.EdwCurrDate.Format("200601") + "01"
		// 	case "#YEARFIRSTDAY":
		// 		retVal = pasInfo.EdwCurrDate.Format("2006") + "0101"
		// 	case "#SYSYEAR":
		// 		retVal = pasInfo.EdwCurrDate.Format("2006")
		// 	case "#SYSMONTH":
		// 		retVal = pasInfo.EdwCurrDate.Format("200601")
		// 	case "#SYSNEXTMONTH":
		// 		retVal = pasInfo.EdwCurrDate.AddDate(0, 1, 0).Format("20060102")
		// 	case "#FTPSYSDATE":
		// 		retVal = pasInfo.FtpCurrDate.Format("20060102")
		// 	case "#FTPSYSMONTH":
		// 		retVal = pasInfo.FtpCurrDate.Format("200601")
		// 	}
		// } else if Sjy == "ODS" {
		// 	switch initValue {
		// 	case "#SYSDATE":
		// 		retVal = pasInfo.CurrDate.Format("20060102")
		// 	case "#MONTHFIRSTDAY":
		// 		retVal = pasInfo.CurrDate.Format("200601") + "01"
		// 	case "#YEARFIRSTDAY":
		// 		retVal = pasInfo.CurrDate.Format("2006") + "0101"
		// 	case "#SYSYEAR":
		// 		retVal = pasInfo.CurrDate.Format("2006")
		// 	case "#SYSMONTH":
		// 		retVal = pasInfo.CurrDate.Format("200601")
		// 	case "#SYSNEXTMONTH":
		// 		retVal = pasInfo.CurrDate.AddDate(0, 1, 0).Format("20060102")
		// 	case "#FTPSYSDATE":
		// 		retVal = pasInfo.FtpCurrDate.Format("20060102")
		// 	case "#FTPSYSMONTH":
		// 		retVal = pasInfo.FtpCurrDate.Format("200601")
		// 	case "#EDWSYSDATE":
		// 		retVal = pasInfo.EdwCurrDate.Format("20060102")
		// 	case "#EDWSYSMONTH":
		// 		retVal = pasInfo.EdwCurrDate.Format("200601")
		// 	case "#EDWMONTHFIRSTDAY":
		// 		retVal = pasInfo.EdwCurrDate.Format("200601") + "01"
		// 	}
		// }
		switch initValue {
		case "#SYSDATE":
			retVal = pasInfo.EdwCurrDate.Format("2006-01-02")
		case "#MONTHFIRSTDAY":
			retVal = pasInfo.EdwCurrDate.Format("2006-01-") + "01"
		case "#YEARFIRSTDAY":
			retVal = pasInfo.EdwCurrDate.Format("2006-") + "01-01"
		case "#SYSYEAR":
			retVal = pasInfo.EdwCurrDate.Format("2006")
		case "#SYSMONTH":
			retVal = pasInfo.EdwCurrDate.Format("200601")
		case "#SYSNEXTMONTH":
			retVal = pasInfo.EdwCurrDate.AddDate(0, 1, 0).Format("2006-01-02")
		}
		return retVal, nil
	}
	return initValue, nil
}

// ReportRequest 报表请求
type ReportRequest struct {
	PermID       int               `json:"permID"`
	ConfigName   string            `json:"configName"`
	ReportParams map[string]string `json:"reportParams"`
	WhereCauses  []base.WhereCause `json:"whereCauses"`
	OrderBY      map[string]string `json:"orderBY"`
	Offset       int               `json:"offset"`
	Limit        int               `json:"limit"`
}

func (r *ReportRequest) paramsToString() string {
	var buff bytes.Buffer
	for _, v := range r.ReportParams {
		buff.WriteString(strings.Replace(v, "-", "", -1))
		buff.WriteString("-")
	}
	if len(r.ReportParams) > 0 {
		buff.Truncate(buff.Len() - 1)
	}
	return buff.String()
}

// ReportDataRouter ReportData路由
func ReportDataRouter(c echo.Context) error {
	rep, repReq, uid, err := getReport(c)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	mgxx, err := getMgxxInfo(repReq.PermID, uid)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	count, err := rep.Create(repReq.WhereCauses, repReq.OrderBY)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	datas, err := rep.GetDataList(repReq.Offset, repReq.Limit, mgxx)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	dataBytes, err := json.Marshal(datas)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	respStr := fmt.Sprintf(`{"total":%d,"datas":%s}`, count, string(dataBytes))
	return c.String(http.StatusOK, respStr)
}

// ReportExportRouter ReportExport路由
func ReportExportRouter(c echo.Context) error {
	rep, repReq, uid, err := getReport(c)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	mgxx, err := getMgxxInfo(repReq.PermID, uid)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	_, err = rep.Create(repReq.WhereCauses, repReq.OrderBY)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	buff, err := rep.ExportXslx(mgxx)
	if err != nil {
		return echo.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	fileName := rep.GetConfig().Name + repReq.paramsToString() + ".xlsx"
	fileName = base64.StdEncoding.EncodeToString([]byte(fileName))
	c.Response().Header().Set("Content-Type", "application/vnd.ms-excel")
	c.Response().Header().Set("Content-Disposition", fileName)
	return c.Blob(http.StatusOK, "application/vnd.ms-excel", buff.Bytes())
}

func getReport(c echo.Context) (reports.Report, *ReportRequest, string, error) {
	req := c.Request()
	repReqBytes, err := ioutil.ReadAll(req.Body)
	if err != nil {
		return nil, nil, "", err
	}
	var repReq ReportRequest
	if err := json.Unmarshal(repReqBytes, &repReq); err != nil {
		return nil, nil, "", err
	}
	user := c.Get("user").(*jwt.Token)
	claims := user.Claims.(*UserLoginClaims)
	rep, err := reports.NewReport(repReq.ConfigName)
	if err != nil {
		return nil, nil, "", err
	}
	if err = rep.SetParams(repReq.ReportParams); err != nil {
		return nil, nil, "", err
	}
	if err = setReportRange(rep, claims, repReq.PermID); err != nil {
		return nil, nil, "", err
	}
	canIdno, err := popedom.IsHasRole(claims.UserID, 19)
	if err != nil {
		return nil, nil, "", err
	}
	rep.SetCanIdno(canIdno)
	return rep, &repReq, strconv.Itoa(claims.UserID), nil
}

func setReportRange(rep reports.Report, claims *UserLoginClaims, permID int) error {
	pTypes, err := popedom.GetUserPermissionTypes(claims.UserID, permID)
	if err != nil {
		return err
	}
	dRange := reports.UserRange
	rangeVal := claims.UserID
	if base.IsInSlice(pTypes, "4") {
		dRange = reports.AllRange
	} else if base.IsInSlice(pTypes, "J") {
		dRange = reports.Dept1Range
		rangeVal = claims.ParentOrgID
	} else if base.IsInSlice(pTypes, "3") {
		dRange = reports.Dept2Range
		rangeVal = claims.OrganID
	}
	rep.SetDataRange(dRange, rangeVal)
	return nil
}

func getMgxxInfo(permID int, uid string) (string, error) {
	rows, err := base.DB.Raw("select dbo.GetMgxxInfo(?,?) mgxx", uid, permID).Rows()
	if err != nil {
		return "", err
	}
	defer rows.Close()
	var (
		mgxx string
	)
	if rows.Next() {
		rows.Scan(&mgxx)
	}
	return mgxx, nil
}

// GetPermissionNameRouter
func GetPermissionNameRouter(c echo.Context) error {
	permID := c.FormValue("permID")
	tx := base.DB.Begin()
	sql := "SELECT PermissionName FROM T_Permission WHERE ID=?"
	row := tx.Raw(sql, permID).Row()
	var pname string
	row.Scan(&pname)
	tx.Commit()
	return c.JSON(http.StatusOK, pname)
}
